﻿using System.Collections.Concurrent;

namespace UtilZ.Dotnet.Ex
{
    /// <summary>
    /// 枚举转换器帮助类
    /// </summary>
    public class EnumParserManager
    {
        static EnumParserManager()
        {
            _lock = new object();
            _enumParserDic = new ConcurrentDictionary<string, IEnumParser>();
        }

        private static readonly object _lock;
        private static readonly ConcurrentDictionary<string, IEnumParser> _enumParserDic;





        private static void PrimitiveAddEnumParser(IEnumParser enumParser)
        {
            _enumParserDic[enumParser.EnumTypeName] = enumParser;
        }

        /// <summary>
        /// 添加枚举解析器
        /// </summary>
        /// <param name="enumParser">枚举解析器</param>
        /// <exception cref="ArgumentNullException">枚举解析器为null将抛出异常</exception>
        public static void AddEnumParser(IEnumParser enumParser)
        {
            if (enumParser == null)
            {
                throw new ArgumentNullException(nameof(enumParser));
            }

            lock (_lock)
            {
                PrimitiveAddEnumParser(enumParser);
            }
        }

        /// <summary>
        /// 获取枚举解析器
        /// </summary>
        /// <param name="enumTypeName">枚举类型名称</param>
        /// <returns>枚举解析器</returns>
        /// <exception cref="ArgumentNullException">枚举类型名称为null或空或全空格将抛出异常</exception>
        /// <exception cref="ArgumentException">枚举类型名称对应的解析器不存在将抛出异常</exception>
        public static IEnumParser GetEnumParser(string enumTypeName)
        {
            if (string.IsNullOrWhiteSpace(enumTypeName))
            {
                throw new ArgumentNullException(nameof(enumTypeName));
            }

            if (_enumParserDic.TryGetValue(enumTypeName, out var enumParser))
            {
                return enumParser;
            }
            else
            {
                throw new ArgumentException($"名称为\"{enumTypeName}\"的解析器不存在");
            }
        }

        /// <summary>
        /// 尝试获取枚举解析器[获取成功返回true,失败返回false]
        /// </summary>
        /// <param name="enumTypeName">枚举类型名称</param>
        /// <param name="enumParser">枚举解析器</param>
        /// <returns>获取成功返回true,失败返回false</returns>
        /// <exception cref="ArgumentNullException">枚举类型名称为null或空或全空格将抛出异常</exception>
        public static bool TryGetEnumParser(string enumTypeName, out IEnumParser enumParser)
        {
            if (string.IsNullOrWhiteSpace(enumTypeName))
            {
                throw new ArgumentNullException(nameof(enumTypeName));
            }

            return _enumParserDic.TryGetValue(enumTypeName, out enumParser);
        }





        private static EnumParser<LogLevel, int> _logLevelEnumParser = null;
        /// <summary>
        /// 日志级别枚举转换器
        /// </summary>
        public static EnumParser<LogLevel, int> LogLevelEnumParser
        {
            get
            {
                if (_logLevelEnumParser == null)
                {
                    lock (_lock)
                    {
                        if (_logLevelEnumParser == null)
                        {
                            var enumStrEnumValueDic = new Dictionary<string, LogLevel>()
                            {
                                { nameof(LogLevel.Trace), LogLevel.Trace },
                                { nameof(LogLevel.Debug), LogLevel.Debug },
                                { nameof(LogLevel.Info), LogLevel.Info },
                                { nameof(LogLevel.Warn), LogLevel.Warn },
                                { nameof(LogLevel.Error), LogLevel.Error},
                                { nameof(LogLevel.Fatal), LogLevel.Fatal },
                                { nameof(LogLevel.Off), LogLevel.Off },
                            };
                            _logLevelEnumParser = new EnumParser<LogLevel, int>(nameof(LogLevel), enumStrEnumValueDic, PrimitiveDataTypes.Int32Type);
                            PrimitiveAddEnumParser(_logLevelEnumParser);
                        }
                    }
                }

                return _logLevelEnumParser;
            }
        }


        private static EnumParser<LockingModel, int> _lockingModelEnumParser = null;
        /// <summary>
        /// 文件日志锁类模型枚举转换器
        /// </summary>
        public static EnumParser<LockingModel, int> LockingModelEnumParser
        {
            get
            {
                if (_lockingModelEnumParser == null)
                {
                    lock (_lock)
                    {
                        if (_lockingModelEnumParser == null)
                        {
                            var enumStrEnumValueDic = new Dictionary<string, LockingModel>()
                            {
                                { nameof(LockingModel.Exclusive), LockingModel.Exclusive },
                                { nameof(LockingModel.InterProcess), LockingModel.InterProcess },
                                { nameof(LockingModel.Minimal), LockingModel.Minimal },
                            };
                            _lockingModelEnumParser = new EnumParser<LockingModel, int>(nameof(LockingModel), enumStrEnumValueDic, PrimitiveDataTypes.Int32Type);
                            PrimitiveAddEnumParser(_lockingModelEnumParser);
                        }
                    }
                }

                return _lockingModelEnumParser;
            }
        }


        private static EnumParser<PrimitiveDataTypes, int> _primitiveTypesEnumParser = null;
        /// <summary>
        /// 文件日志锁类模型枚举转换器
        /// </summary>
        public static EnumParser<PrimitiveDataTypes, int> PrimitiveTypesEnumParser
        {
            get
            {
                if (_primitiveTypesEnumParser == null)
                {
                    lock (_lock)
                    {
                        if (_primitiveTypesEnumParser == null)
                        {
                            var enumStrEnumValueDic = new Dictionary<string, PrimitiveDataTypes>()
                            {
                                { nameof(PrimitiveDataTypes.BoolType), PrimitiveDataTypes.BoolType },
                                { nameof(PrimitiveDataTypes.CharType), PrimitiveDataTypes.CharType },
                                { nameof(PrimitiveDataTypes.ByteType), PrimitiveDataTypes.ByteType },
                                { nameof(PrimitiveDataTypes.SByteType), PrimitiveDataTypes.SByteType },
                                { nameof(PrimitiveDataTypes.Int16Type), PrimitiveDataTypes.Int16Type },

                                { nameof(PrimitiveDataTypes.UInt16Type), PrimitiveDataTypes.UInt16Type },
                                { nameof(PrimitiveDataTypes.Int32Type), PrimitiveDataTypes.Int32Type },
                                { nameof(PrimitiveDataTypes.UInt32Type), PrimitiveDataTypes.UInt32Type },
                                { nameof(PrimitiveDataTypes.Int64Type), PrimitiveDataTypes.Int64Type },
                                { nameof(PrimitiveDataTypes.UInt64Type), PrimitiveDataTypes.UInt64Type },

                                { nameof(PrimitiveDataTypes.Int128Type), PrimitiveDataTypes.Int128Type },
                                { nameof(PrimitiveDataTypes.UInt128Type), PrimitiveDataTypes.UInt128Type },
                                { nameof(PrimitiveDataTypes.BigIntegerType), PrimitiveDataTypes.BigIntegerType },
                                { nameof(PrimitiveDataTypes.FloatType), PrimitiveDataTypes.FloatType },
                                { nameof(PrimitiveDataTypes.DoubleType), PrimitiveDataTypes.DoubleType },

                                { nameof(PrimitiveDataTypes.DecimalType), PrimitiveDataTypes.DecimalType },
                                { nameof(PrimitiveDataTypes.DateTimeType), PrimitiveDataTypes.DateTimeType },
                                { nameof(PrimitiveDataTypes.TimeSpanType), PrimitiveDataTypes.TimeSpanType },
                                { nameof(PrimitiveDataTypes.DateTimeOffsetType), PrimitiveDataTypes.DateTimeOffsetType },
                                { nameof(PrimitiveDataTypes.TimeOnlyType), PrimitiveDataTypes.TimeOnlyType },

                                { nameof(PrimitiveDataTypes.DateOnlyType), PrimitiveDataTypes.DateOnlyType },
                                { nameof(PrimitiveDataTypes.StringType), PrimitiveDataTypes.StringType },
                                { nameof(PrimitiveDataTypes.ReferenceType), PrimitiveDataTypes.ReferenceType },
                                { nameof(PrimitiveDataTypes.ByteAarrayType), PrimitiveDataTypes.ByteAarrayType },

                                { nameof(PrimitiveDataTypes.ShortAarrayType), PrimitiveDataTypes.ShortAarrayType },
                                { nameof(PrimitiveDataTypes.FloatAarrayType), PrimitiveDataTypes.FloatAarrayType },
                                { nameof(PrimitiveDataTypes.Int32AarrayType), PrimitiveDataTypes.Int32AarrayType },
                            };
                            _primitiveTypesEnumParser = new EnumParser<PrimitiveDataTypes, int>(nameof(LockingModel), enumStrEnumValueDic, PrimitiveDataTypes.Int32Type);
                            PrimitiveAddEnumParser(_primitiveTypesEnumParser);
                        }
                    }
                }

                return _primitiveTypesEnumParser;
            }
        }



    }
}